/*  -*-  mode: c; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4; coding: utf-8  -*-  */

#include "usb_conf.h"
#include "diskio.h"
#include "usbh_msc_core.h"
/*--------------------------------------------------------------------------

Module Private Functions and Variables

---------------------------------------------------------------------------*/

static volatile DSTATUS Stat = STA_NOINIT;	/* Disk status */

extern USB_OTG_CORE_HANDLE          USB_OTG_Core;
extern USBH_HOST                     USB_Host;

/*-----------------------------------------------------------------------*/
/* Initialize Disk Drive                                                 */
/*-----------------------------------------------------------------------*/

DSTATUS disk_initialize (
    BYTE drv		/* Physical drive number (0) */
)
{

    if(HCD_IsDeviceConnected(&USB_OTG_Core))
    {
        Stat &= ~STA_NOINIT;
    }

    return Stat;


}



/*-----------------------------------------------------------------------*/
/* Get Disk Status                                                       */
/*-----------------------------------------------------------------------*/

DSTATUS disk_status (
    BYTE drv		/* Physical drive number (0) */
)
{
    if (drv) return STA_NOINIT;		/* Supports only single drive */
    return Stat;
}



/*-----------------------------------------------------------------------*/
/* Read Sector(s)                                                        */
/*-----------------------------------------------------------------------*/

DRESULT disk_read (
    BYTE drv,			/* Physical drive number (0) */
    BYTE *buff,			/* Pointer to the data buffer to store read data */
    DWORD sector,		/* Start sector number (LBA) */
    BYTE count			/* Sector count (1..255) */
)
{
    BYTE status = USBH_MSC_OK;

    if (drv || !count) return RES_PARERR;
    if (Stat & STA_NOINIT) return RES_NOTRDY;


    if(HCD_IsDeviceConnected(&USB_OTG_Core))
    {

        do
        {
            status = USBH_MSC_Read10(&USB_OTG_Core, buff, sector, 512*count);
            USBH_MSC_HandleBOTXfer(&USB_OTG_Core ,&USB_Host);

            if(!HCD_IsDeviceConnected(&USB_OTG_Core))
            {
                return RES_ERROR;
            }
        }
        while(status == USBH_MSC_BUSY );
    }

    if(status == USBH_MSC_OK)
        return RES_OK;
    return RES_ERROR;

}



/*-----------------------------------------------------------------------*/
/* Write Sector(s)                                                       */
/*-----------------------------------------------------------------------*/

#if _READONLY == 0
DRESULT disk_write (
    BYTE drv,			/* Physical drive number (0) */
    const BYTE *buff,	/* Pointer to the data to be written */
    DWORD sector,		/* Start sector number (LBA) */
    BYTE count			/* Sector count (1..255) */
)
{
    BYTE status = USBH_MSC_OK;
    if (drv || !count) return RES_PARERR;
    if (Stat & STA_NOINIT) return RES_NOTRDY;
    if (Stat & STA_PROTECT) return RES_WRPRT;


    if(HCD_IsDeviceConnected(&USB_OTG_Core))
    {
        do
        {
            status = USBH_MSC_Write10(&USB_OTG_Core,(BYTE*)buff, sector, 512*count);
            USBH_MSC_HandleBOTXfer(&USB_OTG_Core, &USB_Host);

            if(!HCD_IsDeviceConnected(&USB_OTG_Core))
            {
                return RES_ERROR;
            }
        }

        while(status == USBH_MSC_BUSY );

    }

    if(status == USBH_MSC_OK)
        return RES_OK;
    return RES_ERROR;
}
#endif /* _READONLY == 0 */



/*-----------------------------------------------------------------------*/
/* Miscellaneous Functions                                               */
/*-----------------------------------------------------------------------*/

#if _USE_IOCTL != 0
DRESULT disk_ioctl (
    BYTE drv,		/* Physical drive number (0) */
    BYTE ctrl,		/* Control code */
    void *buff		/* Buffer to send/receive control data */
)
{
    DRESULT res = RES_OK;

    if (drv) return RES_PARERR;

    res = RES_ERROR;

    if (Stat & STA_NOINIT) return RES_NOTRDY;

    switch (ctrl)
    {
    case CTRL_SYNC :		/* Make sure that no pending write process */

        res = RES_OK;
        break;

    case GET_SECTOR_COUNT :	/* Get number of sectors on the disk (DWORD) */

        *(DWORD*)buff = (DWORD) USBH_MSC_Param.MSCapacity;
        res = RES_OK;
        break;

    case GET_SECTOR_SIZE :	/* Get R/W sector size (WORD) */
        *(WORD*)buff = 512;
        res = RES_OK;
        break;

    case GET_BLOCK_SIZE :	/* Get erase block size in unit of sector (DWORD) */

        *(DWORD*)buff = 512;

        break;


    default:
        res = RES_PARERR;
    }



    return res;
}
#endif /* _USE_IOCTL != 0 */
